/**
 * 
 */
package teamProject;

import java.util.ArrayList;

/**
 * @author Steven Varga
 * 
 */
public class Matrix implements Calculatable {

	/**
	 * 
	 */
	// /////////////////Instance Variables///////////
	int myCols;
	int myRows;
	Calculatable[][] myMatrix;

	public Matrix() {
		myCols = 0;
		myRows = 0;
		myMatrix = new Calculatable[0][0];
	}

	public Matrix(int rows, int cols, ArrayList<Calculatable> list) {
		myRows = rows;
		myCols = cols;
		myMatrix = new Calculatable[rows][cols];
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < myCols; j++) {
				myMatrix[i][j] = list.get(i * myCols + j);
			}
		}
	}

	public int getRows() {
		return myRows;
	}

	public int getColumns() {
		return myCols;

	}

	public Calculatable[][] getMatrix() {
		return myMatrix;
	}

	@Override
	public Calculatable add(Calculatable rhs) {
		if (rhs instanceof Matrix) {
			Matrix mat = (Matrix) rhs.get();
			Calculatable[][] rhsMat = mat.getMatrix();
			if ((this.getRows() == mat.getRows())
					&& this.getColumns() == mat.getColumns()) {
				// this is valid
				// create answer list for new matrix
				ArrayList<Calculatable> answerList = new ArrayList<Calculatable>();
				for (int i = 0; i < myRows; i++) {
					for (int j = 0; j < myCols; j++) {
						answerList.add(myMatrix[i][j].add(rhsMat[i][j]));
					}
				}
				return new Matrix(myRows, myCols, answerList);
			}
		}
		return null;
	}

	@Override
	public Calculatable divide(Calculatable rhs) {
		// TODO Auto-generated method stub
		// can only divide by matrix of same size (each element will divide by
		// its corresponding element in second matrix) or by a polynomial
		ArrayList<Calculatable> answer = new ArrayList<Calculatable>();
		if (rhs instanceof Matrix) {
			Matrix mat = (Matrix) rhs.get();
			Calculatable[][] rhsMat = mat.getMatrix();

			if ((this.getRows() == mat.getRows())
					&& this.getColumns() == mat.getColumns()) {

				for (int i = 0; i < myRows; i++) {
					// will consider first type to be the tempSolution

					for (int j = 0; j < myCols; j++) {

						answer.add(myMatrix[i][j].divide(rhsMat[i][j]));
					}
				}
			}
			return new Matrix(myRows, myCols, answer);
		}

		else {
			for (int i = 0; i < myRows; i++) {
				// will consider first type to be the tempSolution

				for (int j = 0; j < myCols; j++) {
					Calculatable tempAnswer = myMatrix[i][j].divide(rhs);
					if (tempAnswer == null) {
						return null;
					} else {
						answer.add(tempAnswer);
					}
				}
			}
			return new Matrix(myRows, myCols, answer);
		}
	}

	@Override
	public Calculatable multiply(Calculatable rhs) {
		// TODO Auto-generated method stub
		if (rhs instanceof Matrix) {
			Matrix mat = (Matrix) rhs.get();
			Calculatable[][] rhsMat = mat.getMatrix();
			if ((this.getRows() == mat.getColumns()) && this.getRows() != 0) {
				// this is a valid multiplication
				ArrayList<Calculatable> answerList = new ArrayList<Calculatable>();
				ArrayList<Calculatable> multipliedListStill2Add = new ArrayList<Calculatable>();

				for (int i = 0; i < myRows; i++) {
					// will consider first type to be the tempSolution

					for (int j = 0; j < mat.getColumns(); j++) {

						// iterate through each piece and multiply
						for (int k = 0; k < myCols; k++) {
							multipliedListStill2Add.add(myMatrix[i][k]
									.multiply(rhsMat[k][i]));
						}
						Calculatable tempAnswer = multipliedListStill2Add
								.get(0);

						for (int l = 1; l < multipliedListStill2Add.size(); l++) {
							tempAnswer = tempAnswer.add(multipliedListStill2Add
									.get(l));
						}
						answerList.add(tempAnswer);

					}
				}

				return new Matrix(this.getRows(), mat.getColumns(), answerList);
			} else {
				return null; // invalid multiply
			}
		}// Other wise call RHS add method on each individual piece of this
		// matrix with rhs
		else {
			for (int i = 0; i < myRows; i++) {
				for (int j = 0; j < myCols; j++) {
					myMatrix[i][j] = rhs.add(myMatrix[i][j]);
				}
			}
		}
		return null;
	}

	@Override
	public Calculatable negate() {
		// TODO Auto-generated method stub
		for (int i = 0; i < myRows; i++) {
			for (int j = 0; j < myCols; j++) {
				myMatrix[i][j] = myMatrix[i][j].negate();

			}
		}
		return null;
	}

	@Override
	public Calculatable square() {
		// TODO Auto-generated method stub
		return this.multiply(this);
	}

	@Override
	public Calculatable get() {
		// TODO Auto-generated method stub
		return this;
	}

	@Override
	public String toString(){
		String answer = "";
		for(int i = 0; i < myRows; i++){
			answer += "[";
			for(int j = 0; j < myCols - 1; j++){
					answer += myMatrix[i][j].toString() + ",";
			}
			answer += myMatrix[i][myCols - 1].toString() + "], ";
		}
		return answer;
		
	}
}
